Updating UI Dynamically Using setState() in Flutter
In Flutter, the user interface is built from the current state of the application. When a value changes during runtime, the UI needs to reflect that new value. The setState() method is the basic mechanism used inside a State object to notify Flutter that the internal state has changed and that the UI may need to be rebuilt.
When setState() is called, Flutter executes the callback synchronously and schedules the associated State object for rebuilding. If a state value is changed directly without notifying Flutter, the UI may not update to reflect the new value. :contentReference[oaicite:0]{index=0}
1. Learning Objectives
After completing this topic, you will understand:
- What dynamic UI updating means in Flutter.
- Why UI needs to be rebuilt when state changes.
- How
setState() updates the UI.
- How to update text dynamically.
- How to update counters dynamically.
- How to change colors dynamically.
- How to show and hide widgets dynamically.
- How to update lists dynamically.
- How to handle buttons, switches, checkboxes, sliders, and dropdowns.
- How to update UI after asynchronous operations.
- How to avoid common
setState() mistakes.
2. What Does Dynamic UI Mean?
A dynamic UI is an interface whose content, appearance, or behavior changes while the application is running.
For example:
- A counter changes from 0 to 1.
- A button changes its text after being clicked.
- A password field changes between visible and hidden.
- A favorite icon changes when selected.
- A loading indicator appears while data is loading.
- A product quantity changes when the user taps plus or minus.
- A new item appears in a list.
- A selected dropdown value changes.
Flutter uses state changes to determine when the UI should display new information.
3. Why Does the UI Need to Update?
Consider this variable:
int counter = 0;
The UI may display:
Text('$counter')
If the value changes:
counter++;
the Dart variable changes, but changing the variable alone does not tell Flutter that the widget needs to rebuild.
Instead, when the value affects the UI, use:
setState(() {
counter++;
});
This tells Flutter that the state changed and the associated UI may need to be rebuilt. :contentReference[oaicite:1]{index=1}
4. Basic Dynamic UI Flow
User Action
↓
Event Callback
↓
setState()
↓
State Variable Changes
↓
Flutter Schedules Build
↓
build() Runs
↓
New Widget Configuration
↓
Updated UI
For example, when a user presses an Increase button:
onPressed: () {
setState(() {
counter++;
});
}
Flutter rebuilds the relevant widget using the new value.
5. Basic StatefulWidget Structure
Dynamic UI updates using setState() normally happen inside a StatefulWidget.
class CounterScreen extends StatefulWidget {
const CounterScreen({super.key});
@override
State createState() => _CounterScreenState();
}
class _CounterScreenState extends State {
int counter = 0;
@override
Widget build(BuildContext context) {
return Text('$counter');
}
}
The mutable value is stored in the State object. The build() method reads that value and creates the UI.
6. First Dynamic UI Example: Counter
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: CounterScreen(),
);
}
}
class CounterScreen extends StatefulWidget {
const CounterScreen({super.key});
@override
State createState() => _CounterScreenState();
}
class _CounterScreenState extends State {
int counter = 0;
void increaseCounter() {
setState(() {
counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Dynamic Counter'),
),
body: Center(
child: Text(
'$counter',
style: const TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: increaseCounter,
child: const Icon(Icons.add),
),
);
}
}
How it works
- The initial value of
counter is 0.
- The
Text widget displays the counter.
- The user presses the floating action button.
increaseCounter() is called.
setState() changes the value.
- Flutter schedules the widget for rebuilding.
- The
build() method uses the new counter value.
- The user sees the updated number.
7. Updating Text Dynamically
Text can be changed dynamically using a state variable.
String message = 'Hello Flutter';
void changeMessage() {
setState(() {
message = 'Welcome to Flutter';
});
}
Display it using:
Text(message)
Complete example:
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
message,
style: const TextStyle(fontSize: 24),
),
ElevatedButton(
onPressed: changeMessage,
child: const Text('Change Message'),
),
],
)
8. Updating a Button Text Dynamically
The text of a button can also change according to the current state.
bool isSubmitted = false;
void submit() {
setState(() {
isSubmitted = true;
});
}
UI:
ElevatedButton(
onPressed: submit,
child: Text(
isSubmitted ? 'Submitted' : 'Submit',
),
)
Initially, the button displays Submit. After clicking it, the button displays Submitted.
9. Updating UI with Boolean State
Boolean variables are very useful for dynamic UI.
bool isVisible = false;
void toggleVisibility() {
setState(() {
isVisible = !isVisible;
});
}
Use the value to conditionally display a widget:
Column(
children: [
if (isVisible)
const Text(
'This content is now visible',
),
ElevatedButton(
onPressed: toggleVisibility,
child: const Text('Show/Hide'),
),
],
)
10. Show and Hide Widgets Dynamically
A common requirement in applications is to show or hide content based on user interaction.
bool showDetails = false;
void toggleDetails() {
setState(() {
showDetails = !showDetails;
});
}
UI:
Column(
children: [
ElevatedButton(
onPressed: toggleDetails,
child: Text(
showDetails ? 'Hide Details' : 'Show Details',
),
),
if (showDetails)
const Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text(
'Additional product details are displayed here.',
),
),
),
],
)
11. Updating Colors Dynamically
The appearance of a widget can be changed using state.
Color boxColor = Colors.blue;
void changeColor() {
setState(() {
boxColor = Colors.green;
});
}
Use it in the UI:
Container(
width: 150,
height: 150,
color: boxColor,
)
Complete example:
Column(
children: [
Container(
width: 150,
height: 150,
color: boxColor,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: changeColor,
child: const Text('Change Color'),
),
],
)
12. Dynamically Changing Multiple Colors
List colors = [
Colors.red,
Colors.green,
Colors.blue,
];
int selectedColor = 0;
void changeColor() {
setState(() {
selectedColor =
(selectedColor + 1) % colors.length;
});
}
Display:
Container(
width: 150,
height: 150,
color: colors[selectedColor],
)
13. Updating UI with Switch
A switch is commonly used to represent an on/off state.
bool isEnabled = false;
Switch(
value: isEnabled,
onChanged: (value) {
setState(() {
isEnabled = value;
});
},
)
Display the current state:
Text(
isEnabled ? 'Enabled' : 'Disabled',
)
14. Dynamic Dark Mode Example
bool isDarkMode = false;
void toggleTheme() {
setState(() {
isDarkMode = !isDarkMode;
});
}
The switch can update the UI:
Switch(
value: isDarkMode,
onChanged: (value) {
setState(() {
isDarkMode = value;
});
},
)
For a complete application-wide theme change, the state would normally be connected to the application's ThemeData or a broader state-management solution.
15. Updating UI with Checkbox
bool isAccepted = false;
Checkbox(
value: isAccepted,
onChanged: (value) {
setState(() {
isAccepted = value ?? false;
});
},
)
Dynamic text:
Text(
isAccepted
? 'Terms accepted'
: 'Please accept the terms',
)
16. Dynamic Login Button
A login button can change its state when the login process begins.
bool isLoading = false;
Future login() async {
setState(() {
isLoading = true;
});
await Future.delayed(
const Duration(seconds: 2),
);
if (!mounted) return;
setState(() {
isLoading = false;
});
}
UI:
ElevatedButton(
onPressed: isLoading ? null : login,
child: isLoading
? const CircularProgressIndicator()
: const Text('Login'),
)
17. Why Use setState() for Loading UI?
Before the operation starts:
setState(() {
isLoading = true;
});
Flutter rebuilds the UI and displays the loading state.
After the operation completes:
setState(() {
isLoading = false;
});
Flutter rebuilds the UI again and displays the normal button.
18. Updating a List Dynamically
Lists are another common example of dynamic UI.
List fruits = [
'Apple',
'Banana',
];
void addFruit() {
setState(() {
fruits.add('Orange');
});
}
Display the list:
ListView.builder(
itemCount: fruits.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(fruits[index]),
);
},
)
After addFruit() executes, the list is rebuilt and the new item can appear in the UI.
19. Adding and Removing Items Dynamically
List tasks = [];
void addTask(String task) {
setState(() {
tasks.add(task);
});
}
void removeTask(int index) {
setState(() {
tasks.removeAt(index);
});
}
UI:
ListView.builder(
itemCount: tasks.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(tasks[index]),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
removeTask(index);
},
),
);
},
)
20. Complete Dynamic To-Do Example
import 'package:flutter/material.dart';
class TodoScreen extends StatefulWidget {
const TodoScreen({super.key});
@override
State createState() => _TodoScreenState();
}
class _TodoScreenState extends State {
final List tasks = [];
final TextEditingController controller =
TextEditingController();
void addTask() {
final task = controller.text.trim();
if (task.isEmpty) return;
setState(() {
tasks.add(task);
controller.clear();
});
}
void removeTask(int index) {
setState(() {
tasks.removeAt(index);
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Dynamic Todo App'),
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: controller,
decoration: const InputDecoration(
hintText: 'Enter task',
),
),
),
IconButton(
onPressed: addTask,
icon: const Icon(Icons.add),
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: tasks.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(tasks[index]),
trailing: IconButton(
onPressed: () {
removeTask(index);
},
icon: const Icon(Icons.delete),
),
);
},
),
),
],
),
);
}
}
Important Points
- The list is stored in state.
addTask() adds a new item.
removeTask() removes an item.
- Both methods call
setState().
- The ListView reads the latest list during the rebuild.
- The TextEditingController is disposed of when the widget is removed.
21. Updating UI with Slider
double value = 50;
Slider(
value: value,
min: 0,
max: 100,
divisions: 100,
label: value.round().toString(),
onChanged: (newValue) {
setState(() {
value = newValue;
});
},
)
Display the value:
Text(
'Value: ${value.toStringAsFixed(0)}',
)
As the slider moves, the state changes and the displayed value is updated.
22. Updating UI with DropdownButton
String selectedCity = 'Mumbai';
DropdownButton(
value: selectedCity,
items: const [
DropdownMenuItem(
value: 'Mumbai',
child: Text('Mumbai'),
),
DropdownMenuItem(
value: 'Delhi',
child: Text('Delhi'),
),
DropdownMenuItem(
value: 'Pune',
child: Text('Pune'),
),
],
onChanged: (value) {
if (value == null) return;
setState(() {
selectedCity = value;
});
},
)
Display the selected value:
Text('Selected City: $selectedCity')
23. Updating UI with TextField
The onChanged callback of a TextField can be used to update UI state.
String username = '';
TextField(
onChanged: (value) {
setState(() {
username = value;
});
},
)
Display the entered text:
Text(
'Hello $username',
)
For large or complex forms, a TextEditingController, form validation, and more structured state handling may be more appropriate.
24. Dynamic Password Visibility
bool obscurePassword = true;
TextField(
obscureText: obscurePassword,
decoration: InputDecoration(
labelText: 'Password',
suffixIcon: IconButton(
icon: Icon(
obscurePassword
? Icons.visibility
: Icons.visibility_off,
),
onPressed: () {
setState(() {
obscurePassword = !obscurePassword;
});
},
),
),
)
The UI dynamically changes both the password visibility and the icon.
25. Dynamic Favorite Button
bool isFavorite = false;
IconButton(
onPressed: () {
setState(() {
isFavorite = !isFavorite;
});
},
icon: Icon(
isFavorite
? Icons.favorite
: Icons.favorite_border,
),
)
This is a common pattern in product, social media, and content applications.
26. Updating UI with Multiple State Variables
Several related state variables can be changed inside one setState() call.
int score = 0;
String status = 'Not Started';
bool completed = false;
void completeQuiz() {
setState(() {
score = 10;
status = 'Completed';
completed = true;
});
}
The UI can use all three values:
Column(
children: [
Text('Score: $score'),
Text('Status: $status'),
Text(
completed
? 'Quiz Completed'
: 'Quiz In Progress',
),
],
)
27. Updating UI Dynamically with Conditions
Conditional expressions are commonly combined with state.
bool isLoggedIn = false;
Column(
children: [
Text(
isLoggedIn
? 'Welcome back!'
: 'Please log in',
),
isLoggedIn
? const Text('Dashboard')
: ElevatedButton(
onPressed: () {
setState(() {
isLoggedIn = true;
});
},
child: const Text('Login'),
),
],
)
28. Dynamic Shopping Cart Example
int quantity = 1;
final double price = 499;
void increaseQuantity() {
setState(() {
quantity++;
});
}
void decreaseQuantity() {
if (quantity > 1) {
setState(() {
quantity--;
});
}
}
double get totalPrice {
return price * quantity;
}
UI:
Column(
children: [
Text('Price: ₹$price'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: decreaseQuantity,
icon: const Icon(Icons.remove),
),
Text('$quantity'),
IconButton(
onPressed: increaseQuantity,
icon: const Icon(Icons.add),
),
],
),
Text(
'Total: ₹${totalPrice.toStringAsFixed(2)}',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
)
Every quantity change causes the UI to display the new quantity and total price.
29. Updating UI After an Async Operation
Dynamic UI is frequently required when working with APIs, databases, files, or other asynchronous operations.
bool isLoading = false;
String message = '';
Future loadData() async {
setState(() {
isLoading = true;
message = '';
});
await Future.delayed(
const Duration(seconds: 2),
);
if (!mounted) return;
setState(() {
isLoading = false;
message = 'Data loaded successfully';
});
}
UI:
Column(
children: [
if (isLoading)
const CircularProgressIndicator(),
if (!isLoading)
ElevatedButton(
onPressed: loadData,
child: const Text('Load Data'),
),
Text(message),
],
)
30. Do Not Put Async Work Inside setState()
The callback passed to setState() must not be asynchronous. Flutter's API documentation specifies that the callback is executed synchronously and must not return a Future. :contentReference[oaicite:2]{index=2}
Incorrect:
setState(() async {
await loadData();
message = 'Done';
});
Correct:
Future loadData() async {
await fetchData();
if (!mounted) return;
setState(() {
message = 'Done';
});
}
31. Why Check mounted?
An asynchronous operation can finish after the widget has already been removed from the widget tree. Calling setState() after the State has been disposed is an error.
Future loadData() async {
final result = await fetchData();
if (!mounted) return;
setState(() {
data = result;
});
}
Flutter recommends cancelling the work that could trigger the update when possible. Checking mounted can be used as a safeguard before calling setState(). :contentReference[oaicite:3]{index=3}
32. Dynamic UI with Timer
import 'dart:async';
Timer? timer;
int seconds = 0;
@override
void initState() {
super.initState();
timer = Timer.periodic(
const Duration(seconds: 1),
(_) {
if (!mounted) return;
setState(() {
seconds++;
});
},
);
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
Display the timer:
Text(
'Seconds: $seconds',
style: const TextStyle(fontSize: 30),
)
Here the UI updates every second.
33. Updating UI Without setState()
Consider:
int counter = 0;
void increase() {
counter++;
}
The value changes in Dart, but the UI may remain unchanged because Flutter was not notified that the State changed.
Correct:
void increase() {
setState(() {
counter++;
});
}
Flutter's documentation specifically notes that changing state directly without setState() may not schedule a build, so the UI may not reflect the changed state. :contentReference[oaicite:4]{index=4}
34. Keep the setState() Callback Small
The setState() callback should contain the actual state modification rather than unrelated calculations or expensive operations.
Good:
setState(() {
counter++;
});
Less appropriate:
setState(() {
performLargeCalculation();
saveDataToDatabase();
makeApiRequest();
counter++;
});
Better:
final result = performLargeCalculation();
await saveDataToDatabase(result);
if (!mounted) return;
setState(() {
counter++;
});
Flutter recommends using setState() to wrap the actual state change rather than unrelated computation associated with that change. :contentReference[oaicite:5]{index=5}
35. Avoid Unnecessary setState() Calls
Calling setState() unnecessarily can cause additional rebuilding. Flutter's documentation notes that the direct overhead of setState() is small, but the indirect cost of rebuilding the affected widget subtree can be significant. :contentReference[oaicite:6]{index=6}
Instead of:
setState(() {
counter++;
});
setState(() {
message = 'Updated';
});
Related updates can often be combined:
setState(() {
counter++;
message = 'Updated';
});
36. Dynamic UI and build()
The build() method should describe what the UI should look like for the current state.
@override
Widget build(BuildContext context) {
return Text(
counter.toString(),
);
}
When the state changes:
setState(() {
counter++;
});
Flutter schedules a build, and the build() method reads the updated counter.
37. Dynamic UI with Icon Changes
bool isPlaying = false;
IconButton(
onPressed: () {
setState(() {
isPlaying = !isPlaying;
});
},
icon: Icon(
isPlaying
? Icons.pause
: Icons.play_arrow,
),
)
This pattern can be used for play/pause controls, expand/collapse buttons, favorite buttons, and many other interactive elements.
38. Dynamic Expand and Collapse UI
bool expanded = false;
void toggleExpanded() {
setState(() {
expanded = !expanded;
});
}
UI:
Column(
children: [
ListTile(
title: const Text('Flutter'),
trailing: IconButton(
onPressed: toggleExpanded,
icon: Icon(
expanded
? Icons.expand_less
: Icons.expand_more,
),
),
),
if (expanded)
const Padding(
padding: EdgeInsets.all(16),
child: Text(
'Flutter is a UI toolkit for building '
'applications from a single codebase.',
),
),
],
)
39. Dynamic Form Validation
State can also control validation messages.
String email = '';
String errorMessage = '';
void validateEmail() {
setState(() {
if (email.contains('@')) {
errorMessage = '';
} else {
errorMessage = 'Please enter a valid email address';
}
});
}
UI:
Column(
children: [
TextField(
onChanged: (value) {
email = value;
},
),
if (errorMessage.isNotEmpty)
Text(
errorMessage,
style: const TextStyle(
color: Colors.red,
),
),
ElevatedButton(
onPressed: validateEmail,
child: const Text('Validate'),
),
],
)
40. Complete Dynamic Profile Example
class ProfileScreen extends StatefulWidget {
const ProfileScreen({super.key});
@override
State createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State {
String name = 'Manish';
bool isFollowing = false;
int followers = 100;
void toggleFollow() {
setState(() {
isFollowing = !isFollowing;
if (isFollowing) {
followers++;
} else {
followers--;
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Profile'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircleAvatar(
radius: 50,
child: Icon(Icons.person, size: 50),
),
const SizedBox(height: 16),
Text(
name,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text('Followers: $followers'),
const SizedBox(height: 20),
ElevatedButton(
onPressed: toggleFollow,
child: Text(
isFollowing ? 'Following' : 'Follow',
),
),
],
),
),
);
}
}
What changes dynamically?
- The button text changes.
- The follower count changes.
- The action can be performed repeatedly.
- All changes are triggered through
setState().
41. Multiple UI Elements Can React to One State Variable
A single state variable can control multiple widgets.
bool isOnline = false;
The same state can control:
Text(
isOnline ? 'Online' : 'Offline',
)
Icon(
isOnline
? Icons.wifi
: Icons.wifi_off,
)
ElevatedButton(
onPressed: () {
setState(() {
isOnline = !isOnline;
});
},
child: Text(
isOnline ? 'Go Offline' : 'Go Online',
),
)
Changing isOnline updates all of these UI elements during the rebuild.
42. Dynamic UI State Table
| State Type |
Example |
Possible UI Change |
| Integer |
counter |
Text, quantity, score |
| String |
message |
Text content |
| Boolean |
isLoading |
Show/hide widgets |
| Color |
backgroundColor |
Widget appearance |
| List |
tasks |
Dynamic list items |
| Double |
sliderValue |
Slider/value display |
| Enum |
selectedTab |
Selected screen/content |
43. Common Mistakes
Mistake 1: Updating State Without setState()
counter++;
Use:
setState(() {
counter++;
});
Mistake 2: Making setState() Async
setState(() async {
await fetchData();
});
Perform asynchronous work outside the callback.
Mistake 3: Calling setState() After dispose()
Cancel timers, listeners, subscriptions, and other work when appropriate. Use mounted as a safeguard when necessary.
Mistake 4: Putting Heavy Work Inside setState()
Keep database operations, API calls, and expensive calculations outside the callback.
Mistake 5: Calling setState() Repeatedly Without Need
Combine related state updates where practical and avoid redundant rebuilds. :contentReference[oaicite:7]{index=7}
44. Best Practices for Dynamic UI
- Keep state close to the widgets that use it when practical.
- Use
setState() only when the UI needs to respond to the state change.
- Keep the
setState() callback small.
- Do not perform asynchronous work inside the callback.
- Use
mounted when an asynchronous operation may finish after widget disposal.
- Cancel timers and subscriptions in
dispose().
- Use
const widgets where possible.
- Split very large widgets into smaller widgets.
- Avoid unnecessary rebuilds.
- For complex shared state, consider a dedicated state-management architecture.
45. setState() vs Direct Assignment
| Direct Assignment |
Using setState() |
| Changes a Dart variable. |
Changes the variable and notifies Flutter. |
| Does not itself schedule a widget rebuild. |
Schedules the State object for rebuilding. |
| Suitable when the changed value does not affect this UI. |
Suitable when the changed value affects the UI. |
46. Dynamic UI Update Example: Before and After
Initial State
int counter = 0;
UI:
Counter: 0
User Action
setState(() {
counter++;
});
New State
int counter = 1;
UI becomes:
Counter: 1
The same process can happen for text, colors, lists, buttons, images, visibility, loading indicators, and other UI elements.
47. Interview Questions
Q1. What is dynamic UI in Flutter?
Dynamic UI is an interface that changes according to user interaction, application state, asynchronous data, or other runtime conditions.
Q2. How do you update UI dynamically using setState()?
Change the relevant state variable inside the setState() callback. Flutter then schedules the State object for rebuilding.
Q3. Why does the UI not always update when a variable changes?
Changing a state variable directly does not itself notify Flutter to rebuild the relevant widget.
Q4. Can I use await inside setState()?
No. The callback passed to setState() must not return a Future. Perform the asynchronous operation separately and then update the state synchronously.
Q5. What is mounted used for?
It can be checked before calling setState() after asynchronous work to verify that the State is still mounted.
Q6. Can multiple values be updated in one setState()?
Yes. Multiple related state variables can be changed inside one callback.
Q7. Why should unnecessary setState() calls be avoided?
Calling setState() can cause the relevant widget subtree to rebuild, so unnecessary calls can increase the work Flutter performs.
48. Practice Exercises
- Create a counter with Increase, Decrease, and Reset buttons.
- Create a button that changes its text after clicking.
- Create a box whose color changes between three colors.
- Create a show/hide password field.
- Create a favorite icon that changes when clicked.
- Create a dynamic shopping cart quantity selector.
- Create a to-do list with Add and Delete functionality.
- Create a loading button that displays a progress indicator for two seconds.
- Create a dropdown that dynamically displays the selected city.
- Create a slider that dynamically displays its numeric value.
- Create an expandable card using a Boolean state variable.
- Create a simple profile screen with Follow/Unfollow functionality.
49. Quick Revision
| Concept |
Purpose |
| State |
Stores information that can change during runtime. |
| StatefulWidget |
Provides a widget structure that can maintain mutable state. |
| setState() |
Notifies Flutter that the State has changed and may need rebuilding. |
| build() |
Creates the widget configuration based on the current state. |
| mounted |
Indicates whether the State is currently mounted. |
| dispose() |
Used to clean up resources when State is permanently removed. |
50. Official Flutter Resource
For detailed information about setState(), see the official Flutter API documentation:
Flutter setState() API Documentation
51. Flutter Training Resources
For structured Flutter training and practical learning resources, visit:
JustAcademy Flutter Training
To register for a course demo:
Register for Flutter Course Demo
52. Key Takeaways
- Dynamic UI means that the interface changes while the application is running.
setState() is the basic Flutter mechanism for notifying a State object that its internal state has changed.
- When
setState() is called, Flutter schedules the associated State object for rebuilding.
- The
build() method uses the latest state to produce the updated UI.
- Text, colors, buttons, lists, icons, loading indicators, switches, checkboxes, sliders, and other widgets can all react to state changes.
- The
setState() callback should be synchronous and focused on actual state changes.
- Asynchronous work should be performed outside the
setState() callback.
- After asynchronous work, check
mounted when necessary before updating state.
- Cancel ongoing work such as timers and subscriptions during
dispose() where appropriate.
- Avoid unnecessary
setState() calls because rebuilding widget subtrees can have an indirect performance cost. :contentReference[oaicite:8]{index=8}
Conclusion
Updating the UI dynamically using setState() is one of the most important Flutter concepts for building interactive applications. Whenever local state changes and that change should be reflected in the interface, setState() provides Flutter with the notification needed to rebuild the relevant UI. By practicing counters, forms, lists, loading states, switches, shopping carts, and other interactive examples, developers can build a strong foundation for more advanced Flutter state-management techniques.